package socket

import (
	"api-gateway-core/session"
	"bufio"
	"fmt"
	"github.com/evanphx/wildcat"
	"github.com/panjf2000/gnet/v2"
	"log"
	"net/http"
	"strings"
)

var (
	errMsg      = "Internal Server Error"
	errMsgBytes = []byte(errMsg)
)

type httpServer struct {
	gnet.BuiltinEventEngine
	ip                    string
	port                  string
	gatewaySessionFactory *session.GatewaySessionFactory
	multicore             bool
	eng                   gnet.Engine
}

func (hs *httpServer) OnBoot(eng gnet.Engine) gnet.Action {
	hs.eng = eng
	log.Printf("echo server with multi-core=%t is listening on %s:%s\n", hs.multicore, hs.ip, hs.port)
	return gnet.None
}

func (hs *httpServer) OnOpen(c gnet.Conn) ([]byte, gnet.Action) {
	c.SetContext(&httpCodec{parser: wildcat.NewHTTPParser()})
	return nil, gnet.None
}

func (hs *httpServer) OnTraffic(c gnet.Conn) gnet.Action {
	hc := c.Context().(*httpCodec)
	buf, _ := c.Next(-1)
	// 创建一个Reader来读取原始请求文本
	reader := strings.NewReader(string(buf))
	// 创建一个http.Request对象
	request, err := http.ReadRequest(bufio.NewReader(reader))
	if err != nil {
		panic(err)
	}
	hc.request = request
pipeline:
	headerOffset, err := hc.parser.Parse(buf)
	if err != nil {
		c.Write(errMsgBytes)
		return gnet.Close
	}
	hc.appendResponseHeader()
	hc.handler(hs.gatewaySessionFactory)
	bodyLen := int(hc.parser.ContentLength())
	if bodyLen == -1 {
		bodyLen = 0
	}
	buf = buf[headerOffset+bodyLen:]
	if len(buf) > 0 {
		goto pipeline
	}
	c.Write(hc.buf)
	hc.buf = hc.buf[:0]
	return gnet.None
}

func NewGatewaySocketServer(gatewaySessionFactory *session.GatewaySessionFactory) {
	var port string = gatewaySessionFactory.Configuration.Port
	var hostName string = gatewaySessionFactory.Configuration.HostName
	hs := &httpServer{ip: fmt.Sprintf("tcp://%s", hostName), port: port, multicore: true, gatewaySessionFactory: gatewaySessionFactory}
	// Start serving!
	log.Println("server exits:", gnet.Run(hs, fmt.Sprintf("%s:%s", hs.ip, hs.port), gnet.WithMulticore(true)))
}
